package com.carwler.demo;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.carwler.demo.domain.CarBrand;
import com.carwler.demo.domain.CarSerious;
import com.carwler.demo.domain.CarType;
import com.carwler.demo.domain.SimpleBrand;
import com.carwler.demo.domain.SimpleSerious;
import com.carwler.demo.domain.SimpleSeriousList;
import com.carwler.demo.domain.SimpleType;
import com.carwler.demo.domain.SimpleTypeList;
import com.carwler.demo.domain.SimpleTypeTemp;
import com.carwler.demo.domain.SimpleTypeTemp2;
import com.carwler.demo.repository.CarBrandRepository;
import com.carwler.demo.repository.CarSeriousRepository;
import com.carwler.demo.repository.CarTypeRepository;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 汽车之家
 * 
 * @version 1.0
 * @author fuhw
 */
@Service
public class QczjCrawler implements Runnable {

	private static final String TYPE_IMG_PATH = "D:\\qczj-type-logo\\";
	private static final String HTTP_PRX_FIX = "http://";
	
	private static final String BASE_URL = "http://car.autohome.com.cn/javascript/NewSpecCompare.js";

	private static final String BASE_TYPE_URL = "http://car.autohome.com.cn/duibi/chexing/carids={typeId},0,0,0";

	private static final String BASE_SERIA_URL = "http://car.autohome.com.cn/duibi/ashx/SpecCompareHandler.ashx?type=2&seriesid={seriesid}&isie6=0";

	private static final ObjectMapper MAPPER = new ObjectMapper();

	private static final Logger LOGGER = LoggerFactory.getLogger( QczjCrawler.class );

	private final CarBrandRepository brandRepository;

	private final CarSeriousRepository seriousRepository;

	private final CarTypeRepository typeRepository;

	public QczjCrawler( CarBrandRepository brandRepository, CarSeriousRepository seriousRepository, CarTypeRepository typeRepository ) {
		super();
		this.brandRepository = brandRepository;
		this.seriousRepository = seriousRepository;
		this.typeRepository = typeRepository;
	}

	public QczjCrawler() {
		super();
		this.brandRepository = null;
		this.seriousRepository = null;
		this.typeRepository = null;
	}

	/**
	 * 获取品牌-车型数据 格式： [{ "I": 117, "N": "AC Schnitzer", "L": "A", "List": [ {
	 * "I": 305, "N": "AC Schnitzer", "List": [ { "I": 3895, "N": "AC Schnitzer
	 * M3" }, { "I": 2097, "N": "AC Schnitzer X5" } ] } ] }]
	 * 
	 * @return
	 * @author fuhw
	 */
	private List<SimpleBrand> getSimpleTypes(){
		LOGGER.info( "开始抓取车型索引数据:" );
		List<SimpleBrand> simpleBrands = new ArrayList<>();
		List<String> wrrors = new ArrayList<>();
		try {
			String datasStr = HttpPool.doGetRequest( BASE_URL );
			datasStr = datasStr.split( "= " )[1];
			datasStr = datasStr.substring( 0, datasStr.length() - 3 );
			simpleBrands = MAPPER.readValue( datasStr, new TypeReference<List<SimpleBrand>>() {} );
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (wrrors != null && !wrrors.isEmpty()) {
			LOGGER.info( "抓取失败的数据:" + wrrors );
		}
		LOGGER.info( "抓取索引记录：[{}] 条.", simpleBrands.size() );
		return simpleBrands;
	}

	/**
	 * 
	 * 根据车型id，获取车系数据 数据格式： { "I": 3895, "List": [ { "I": 1, "N": "在售车型", "List":
	 * [ { "I": 2015, "List": [ { "I": 23562, "N": "ACS3 sport", "P": 1090000 }
	 * ] } ] } ] }
	 * 
	 * @param seriesid 车系id
	 * @return 车型列表
	 * @author fuhw
	 */
	private List<CarType> getCarTypes( String seriesid ){
		LOGGER.info( "开始抓取车系[{}]下的车型数据、", seriesid );
		List<CarType> carTypes = new ArrayList<>();
		List<String> wrrors = new ArrayList<>();
		String startUrl = StringUtils.replace( BASE_SERIA_URL, "{seriesid}", seriesid );
		try {
			String typeTemp = HttpPool.doGetRequest( startUrl );
			SimpleTypeTemp typeList = MAPPER.readValue( typeTemp, SimpleTypeTemp.class );
			List<SimpleTypeTemp2> list = typeList.getList();
			if (list == null) return carTypes;
			for (SimpleTypeTemp2 simpleTypeTemp2 : list) {
				List<SimpleTypeList> list2 = simpleTypeTemp2.getList();
				if (list2 == null || list2.isEmpty()) continue;
				for (SimpleTypeList simpleTypeList : list2) {
					/**
					 * "List": [ { "I": 2015, "List": [ { "I": 23562, "N": "ACS3
					 * sport", "P": 1090000 } ] } ]
					 */
					List<SimpleType> list3 = simpleTypeList.getList();
					if (list3 == null || list3.isEmpty()) continue;
					String marketYear = simpleTypeList.getN();// 上市年份
					/**
					 * 车型数据 "List": [ { "I": 23562, "N": "ACS3 sport", "P":
					 * 1090000 } ]
					 */
					for (SimpleType simpleType : list3) {
						CarType carType = new CarType();
						carType.setMarketYear( marketYear );
						carType.setName( simpleType.getN() );
						parseDatas( carType, simpleType.getI() + "" );
						carTypes.add( carType );
					}
				}
			}
			carTypes.add( null );
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (wrrors != null && !wrrors.isEmpty()) {
			LOGGER.info( "没有读取成功的数据：" + wrrors );
		}
		return carTypes;
	}

	
	public void executeCrawler(){
		List<SimpleBrand> brands = this.getSimpleTypes();
		if (brands == null || brands.isEmpty()) return;
		List<CarType> allCarTypes = new ArrayList<>();
		List<CarBrand> allCarBrands = new ArrayList<>();
		List<CarSerious> allCarSerious = new ArrayList<>();
		/**
		 * 遍历索引
		 */
//		for (int i = 0; i < 5; i++) {
//			SimpleBrand simpleBrand = brands.get( i );
		for (SimpleBrand simpleBrand : brands) {
			/** 添加品牌 */
			allCarBrands.add( new CarBrand( simpleBrand.getN() ) );
			List<SimpleSeriousList> list = simpleBrand.getList();
			if (list == null || list.isEmpty()) continue;
			for (SimpleSeriousList simpleSeriousList : list) {
				List<SimpleSerious> list2 = simpleSeriousList.getList();
				if (list2 == null || list2.isEmpty()) continue;
				for (SimpleSerious simpleType : list2) {
					/** 添加车系 */
					allCarSerious.add( new CarSerious( simpleType.getN() ) );
					/** 添加车型 */
					List<CarType> carTypes = this.getCarTypes( simpleType.getI() + "" );
					for (CarType type : carTypes) {
						if (type == null) continue;
						type.setBrandName( simpleBrand.getN() );
						type.setSeriousName( simpleType.getN() );
						allCarTypes.add( type );
					}
				}
			}
		}
		/*** 持久化数据 */
		if (!allCarBrands.isEmpty()) brandRepository.save( allCarBrands );
		if (!allCarSerious.isEmpty()) seriousRepository.save( allCarSerious );
		if (!allCarTypes.isEmpty()) typeRepository.save( allCarTypes );
	}
	/**
	 * 获取生成年份
	 * 
	 * @param temp
	 * @return
	 * @author fuhw
	 * @throws Exception 
	 */
	// private String getMarketYear(String temp) {
	// Pattern yearPattern = Pattern.compile( "(\\d{4})款" );
	// Matcher matcher = yearPattern.matcher( temp );
	// if(matcher.find()){
	// return matcher.group( 1 );
	// }
	// return null;
	// }

//	public static void main( String[] args ) throws Exception{
////		HttpPool.downloadFile( "http://car0.autoimg.cn/upload/spec/1424/s_1424123874236.jpg", new File( "D:\\qczj-type-logo\\"+"s_1424123874236.jpg" ) );
////		QczjCrawler crawler = new QczjCrawler();
////		crawler.parseDatas( new CarType(), "1424" );
//		String temp = "http://car0.autoimg.cn/upload/spec/1424/s_1424123874236.jpg";
//		if (temp.startsWith( HTTP_PRX_FIX )) {
//			System.out.println( "asdfagfdasgf" );
//		}
//	}
	
	/**
	 * 解析车型详情数据，填充字段值
	 * 
	 * @param carType
	 * @param typeId
	 * @author fuhw
	 */
	public void parseDatas( CarType carType, String typeId ){
		String startUrl = StringUtils.replace( BASE_TYPE_URL, "{typeId}", typeId );
		String html;
		try {
			html = HttpPool.doGetRequest( startUrl );
			Document document = Jsoup.parse( html );
			Elements titleInfos = document.getElementById( "tbSpecInfo" ).select( "td" );// 车型信息table
			
			/**获取图片*/
			Elements logoTypes = document.getElementsByClass( "js-hitems tablechoice" ).select( "td" );// 车型图片
			Elements elementsByClass = logoTypes.get( 1 ).getElementsByClass( "text-ul-pic" );
			String imgUrl = elementsByClass.select( "img" ).attr( "src" );
			if(StringUtils.isNoneBlank( imgUrl )) {
				if (!imgUrl.startsWith( HTTP_PRX_FIX )) {
					imgUrl = HTTP_PRX_FIX + imgUrl;
				}
				String[] split = imgUrl.split( "/" );  
				String temp = split[split.length-1];//图片名
				HttpPool.downloadFile( imgUrl, new File( TYPE_IMG_PATH+temp ) );
				carType.setImg( temp );
			}
			
			/**获取基础数据**/
			Elements tables = document.getElementsByClass( "js-titems tableinfo" ).select( "tr" );// 表格参数
			// private String name;// 车型
			// private String marketYear;// 上市年份 carType.setMarketYear(
			// getMarketYear(name) );修改为从车系数据中获取
			// private String fullName;// 车型全称
			// private BigDecimal price;// 厂商指导价
			carType.setFullName( getElementsValue( titleInfos, 0 ) );
			carType.setPrice( getElementsValue( titleInfos, 4 ) );
			/******* 基础 ********/
			carType.setMakerName( getElementsValue( tables, 0 ) );
			carType.setLevel( getElementsValue( tables, 1 ) );
			carType.setEngineName( getElementsValue( tables, 2 ) );
			carType.setGearbox( getElementsValue( tables, 3 ) );
			carType.setMaxSpeed( getElementsValue( tables, 6 ) );
			carType.setFuelConsume( getElementsValue( tables, 12 ) );
			/******** 车身 ***********/
			carType.setLen( getElementsValue( tables, 15 ) );
			carType.setWeight( getElementsValue( tables, 16 ) );
			carType.setHeight( getElementsValue( tables, 17 ) );
			carType.setWheelBase( getElementsValue( tables, 18 ) );
			carType.setFrontTrack( getElementsValue( tables, 19 ) );
			carType.setBearTrack( getElementsValue( tables, 20 ) );
			carType.setMinGapGround( getElementsValue( tables, 21 ) );
			carType.setQuality( getElementsValue( tables, 22 ) );
			carType.setStructure( getElementsValue( tables, 23 ) );
			carType.setDoorCounts( getElementsValue( tables, 24 ) );
			carType.setSeatCounts( getElementsValue( tables, 25 ) );
			carType.setTankVolume( getElementsValue( tables, 26 ) );
			carType.setTrankCapacity( getElementsValue( tables, 27 ) );
			/********* 发动机 **************/
			carType.setEngineType( getElementsValue( tables, 28 ) );
			carType.setDisplacement( getElementsValue( tables, 29 ) );
			carType.setAirIntakeForm( getElementsValue( tables, 30 ) );
			carType.setCylinderArr( getElementsValue( tables, 31 ) );
			carType.setCylinderCounts( getElementsValue( tables, 32 ) );
			carType.setValveCounts( getElementsValue( tables, 33 ) );
			carType.setCompressionRatio( getElementsValue( tables, 34 ) );
			carType.setGasStructure( getElementsValue( tables, 35 ) );
			carType.setCylinderDiameter( getElementsValue( tables, 36 ) );
			carType.setStroke( getElementsValue( tables, 37 ) );
			carType.setMaxHorsepower( getElementsValue( tables, 38 ) );
			carType.setMaxPower( getElementsValue( tables, 39 ) );
			carType.setMaxPowerRatoteSpeed( getElementsValue( tables, 40 ) );
			carType.setMaxTorque( getElementsValue( tables, 41 ) );
			carType.setMaxTorqueRatoteSpeed( getElementsValue( tables, 42 ) );
			carType.setFuelName( getElementsValue( tables, 44 ) );
			carType.setFuelNumber( getElementsValue( tables, 45 ) );
			carType.setFuelType( getElementsValue( tables, 46 ) );
			carType.setCylinderHeadMeterial( getElementsValue( tables, 47 ) );
			carType.setCylinderBodyMeterial( getElementsValue( tables, 48 ) );
			/*********** 变速箱 ***************/
			carType.setGearboxName( getElementsValue( tables, 50 ) );
			carType.setStallCounts( getElementsValue( tables, 51 ) );
			carType.setGearboxType( getElementsValue( tables, 52 ) );
			/*****************/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取指定值
	 * 
	 * @param tables 表格文档对象
	 * @param index 表格索引
	 * @return
	 * @author fuhw
	 */
	private String getElementsValue( Elements tables, int index ){
		if(tables.size() <= index) return null;
		return tables.get( index ).select( "td" ).get( 0 ).text();
	}

	@Override
	public void run(){
		System.err.println("任务开始执行:");  
        try {  
            Thread.sleep(3000);  
            this.executeCrawler();
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.err.println("任务执行完毕！！！");  
	}

	

}
